﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IsreversI
{
    /// <summary>
    /// Utility class for working with ordered pairs of integers.
    /// 
    /// All standard library vectors are based on floats or doubles, and the
    /// Point class doesn't allow multiplication, so I guess I'll have to
    /// write my own.
    /// </summary>
    /// <remarks>
    /// Yay for linear algebra!
    /// </remarks>
    class IntVector2
    {
        public readonly int X = 0, Y = 0;

        /// <summary>
        /// Get the length of the vector in *tiles*.  This is the number of
        /// steps necessary to reach one tile from the other, with diagonal
        /// moves allowed.
        /// </summary>
        public int TileLength
        {
            get
            {
                return Math.Max(Math.Abs(this.X), Math.Abs(this.Y));
            }
        }

        public IntVector2(int X, int Y)
        {
            this.X = X;
            this.Y = Y;
        }

        public IntVector2(Point p) : this(p.X, p.Y) { }

        public static implicit operator IntVector2(Point p)
        {
            return new IntVector2(p);
        }

        public static implicit operator Point(IntVector2 v)
        {
            return new Point(v.X, v.Y);
        }

        public static IntVector2 operator +(IntVector2 f, IntVector2 s)
        {
            return new IntVector2(f.X + s.X, f.Y + s.Y);
        }

        public static IntVector2 operator -(IntVector2 f, IntVector2 s)
        {
            return new IntVector2(f.X - s.X, f.Y - s.Y);
        }

        public static IntVector2 operator *(int lambda, IntVector2 vector)
        {
            return new IntVector2(lambda * vector.X, lambda * vector.Y);
        }

        public static bool operator ==(IntVector2 f, IntVector2 s)
        {
            return f.Equals(s);
        }

        public static bool operator !=(IntVector2 f, IntVector2 s)
        {
            return !f.Equals(s);
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            IntVector2 v = obj as IntVector2;
            if ((object)v == null)
                return false;
            return this.X == v.X && this.Y == v.Y;
        }

        public bool Equals(IntVector2 v)
        {
            if (v == null)
                return false;
            return this.X == v.X && this.Y == v.Y;
        }

        public override int GetHashCode()
        {
            // Roll X half-way through, then xor it with Y.
            return ((this.X << 16) | (this.X >> 16)) ^ this.Y;
        }

        public override string ToString()
        {
            return "X = " + X + ", Y = " + Y;
        }

        /// <summary>
        /// Returns true if the vectors are on the same line in terms of tiles.
        /// </summary>
        public static bool OnLine(IntVector2 f, IntVector2 s)
        {
            IntVector2 diff = f - s;
            if (diff.X == 0 || diff.Y == 0)
                return true;
            if (Math.Abs(diff.X) == Math.Abs(diff.Y))
                return true;
            return false;
        }
    }
}
